package cn.isjinhao.se.sql;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
 * @Author ISJINHAO
 * @Date 2021/7/18 10:47
 */
public abstract class AbstractErrorReporterDelegate implements ErrorReporter {

    protected static final String SEPARATOR = " ";

    private Map<Class<? extends Error>, Function<? super Error, String>> msgSuffix = new ErrorMsgFunctionMap();

    public static final int ERROR_CODE_BOOTSTRAP = 90000;

    protected Map<Integer, String> digitizedErrorMsg = new HashMap<>();

    public AbstractErrorReporterDelegate() {
        fillErrorMsg();
    }

    protected abstract void fillErrorMsg();

    protected String getErrorMsg(int errorCode) {
        return digitizedErrorMsg.get(errorCode);
    }

    protected void addErrorMsg(int errorCode, String errorMsg) {
        if (digitizedErrorMsg.containsKey(errorCode)) {
            throw new SqlException(ERROR_CODE_BOOTSTRAP, "The code of error has existed, current msg is : " + getErrorMsg(errorCode) + ".");
        }
        digitizedErrorMsg.put(errorCode, errorMsg);
    }

    protected void addSuffixFunction(Class<? extends Error> type, Function<? super Error, String> function) {
        msgSuffix.put(type, function);
    }


    protected String getSuffix(Error attachment) {
        Function<? super Error, String> stringFunction = msgSuffix.get(attachment);
        return stringFunction.apply(attachment);
    }

    private class ErrorMsgFunctionMap extends HashMap<Class<? extends Error>, Function<? super Error, String>> {

        @Override
        public Function<? super Error, String> get(Object object) {
            Set<Entry<Class<? extends Error>, Function<? super Error, String>>> entries = this.entrySet();

            for (Entry<Class<? extends Error>, Function<? super Error, String>> entry : entries) {
                Class<? extends Error> key = entry.getKey();
                if (key.isAssignableFrom(object.getClass())) {
                    return entry.getValue();
                }
            }

            return null;
        }
    }

}
